import { _decorator, Component, Node, CCBoolean, Enum, Vec3, Camera, find, Vec2, game, clamp01, Animation, Color, Quat } from 'cc';
import { EDITOR, QTT } from 'cc/env';
import { DebugDraw } from '../utils/debugDraw';
import { SmoothPath } from '../utils/smooth_path';
const { ccclass, property, executeInEditMode } = _decorator;

let _tempVec3: Vec3 = new Vec3;
let _tempQuat: Quat = new Quat;
export enum MoveType {
    Loop,                       // 循环
    PingPong,                   // 反复
    Normal,                     // 正常播放一次
    UseAnimation,               // 使用动画
}

@ccclass('OrbitCamera')
@executeInEditMode
export class OrbitCamera extends Component {
    @property({ type: Enum(MoveType), tooltip: '移动类型' })
    moveType: MoveType = MoveType.Normal;

    @property({ type: Node, tooltip: "跟随对象做相对运动", visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    follow: Node | null = null;

    @property({ type: Node, tooltip: "是否对准对象", visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    lookAt: Node | null = null;

    @property({ type: Node, tooltip: '移动路径节点父节点', visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    moveNodePanel: Node | null = null;

    @property({ type: CCBoolean, tooltip: '是否启用平滑移动', visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    useSmoothPath: boolean = false;

    @property({ tooltip: '在编辑器中显示曲线', visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    public set showSmoothPath (value: boolean) {
        this._showSmoothPath = value;
        this._drawSmoothPath(value);
    };

    public get showSmoothPath () {
        return this._showSmoothPath;
    }
    private _showSmoothPath = false;


    @property({ tooltip: '位移速度', visible (this: OrbitCamera) { return this.moveType != MoveType.UseAnimation } })
    moveSpeed: number = 1;

    @property({ tooltip: '是否允许Pitch旋转(绕x轴)', visible (this: OrbitCamera) { return this.lookAt == null } })
    rotateXEnable: boolean = false;

    @property({ tooltip: '是否允许yaw旋转(绕y轴)', visible (this: OrbitCamera) { return this.lookAt == null } })
    rotateYEnable: boolean = false;

    @property({ tooltip: '旋转速度', visible (this: OrbitCamera) { return this.lookAt == null && (this.rotateXEnable || this.rotateYEnable) } })
    rotateSpeed: number = 30;

    @property({
        tooltip: "移动进度。\n除动画外是百分比，其余是path上的点的index。",
    })
    get progress () {
        return this._progress;
    }
    set progress (v: number) {
        if (this._progress !== v) {
            this._progress = v;
            // if (CC_EDITOR) game.emit(CinestationEvent.EDITOR_CHANGED);
        }
    }

    @property(CCBoolean)
    playOnLoad: boolean = false;

    private _progress: number = 0;

    private _camera: Camera | null = null;
    private _targetPosition: Vec3 = new Vec3;
    private _positions: Vec3[] = [];
    private _isPlay = false;

    private _primary: Vec2 | null = null;
    private _smoothPath: SmoothPath | null = null;
    private _dir: number = 1;
    private _debugName: string = "";

    start () {
        this._camera = this.node.getComponent(Camera);
        if (!this._camera) {
            let mainNode = find("Main Camera");
            if (mainNode) {
                this._camera = mainNode.getComponent(Camera);
            }
        }
        if (this.moveNodePanel) {
            let list: Vec3[] = [];
            this.moveNodePanel.children.forEach((node) => {
                list.push(node.position);
            })
            this.setMovePositions(list);
        }

        if (this.playOnLoad && !EDITOR) {
            this.play();
        }
    }

    // 绑定输入
    public bindInput (primary: Vec2 | null, scroll: Vec2 | null) {
        this._primary = primary;
    }

    /**
     * 设置移动路径点
     */
    public setMovePositions (list: Vec3[]) {
        this._positions = list;

        if (this.useSmoothPath) {
            this._smoothPath = new SmoothPath(this._positions, this.moveType == MoveType.Normal ? false : true);
        }
    }

    /**
     * 重新播放
     */
    public reset () {
        this._isPlay = false;
        // 归位
        if (this.moveType != MoveType.UseAnimation) {
            this.progress = 0;
            this.node.position = this._positions[this.progress];
        } else {
            //  this.getComponent(Animation)!.stop();
        }
    }

    update (deltaTime: number) {
        if (!this._isPlay) {
            return;
        }

        this.updatePathPosition(deltaTime)
        this.applyInput(deltaTime);
        this.applyFollowNode();
        // 混合
        // this._lerpTime += deltaTime * this._dir; // 混合
        // from.worldPosition = from.worldPosition.lerp(this._targetPosition, clamp01(this._lerpTime / this._positions.length));
        let from = this._camera ? this._camera.node : this.node;
        from.setWorldPosition(this._targetPosition);

        this._updateProgress(deltaTime);

        // 是否看向目标
        if (this.lookAt) {
            from.getWorldPosition(_tempVec3);
            Vec3.subtract(_tempVec3, _tempVec3, this.lookAt.worldPosition);
            Vec3.normalize(_tempVec3, _tempVec3);

            Quat.fromViewUp(_tempQuat, _tempVec3, Vec3.UP);
            from.setRotation(_tempQuat);
        }
    }

    /**
     * 更新进度
     * @param deltaTime 
     */
    private _updateProgress (deltaTime: number) {
        this.progress += deltaTime * this._dir;
        if (this.progress >= this._positions.length || this.progress <= 0) {
            if (this.moveType == MoveType.Normal) {
                this._isPlay = false;
            } else if (this.moveType == MoveType.Loop) {
                this.progress = 0;
            } else if (this.moveType == MoveType.PingPong) {
                this._dir = -this._dir;
                if (this.progress < 0) {
                    this.progress = 0;
                } else if (this.progress >= this._positions.length) {
                    this.progress = this._positions.length;
                }
            }
        }

    }

    // 更新坐标
    public updatePathPosition (deltaTime: number) {
        if (this.moveType == MoveType.UseAnimation) {
            // animeCurve
        } else {
            if (this._smoothPath) {
                this._smoothPath.evaluatePosition(this._targetPosition, this.progress);
            } else {
                let startIndex = (this._dir > 0 ? Math.floor(this.progress) : Math.ceil(this.progress));
                let progress = this.progress - startIndex;
                startIndex = startIndex % this._positions.length;

                let nextIndex = (startIndex + this._dir) % this._positions.length;
                if (nextIndex < 0) {
                    nextIndex = this._positions.length - 1;
                }
                Vec3.subtract(this._targetPosition, this._positions[nextIndex], this._positions[startIndex])
                this._targetPosition.multiplyScalar(progress * this._dir);
                Vec3.add(this._targetPosition, this._targetPosition, this._positions[startIndex])
            }
        }
    }

    // 应用输入
    public applyInput (deltaTime: number) {
        if (this.lookAt || !this._camera) {
            return;
        }

        // targetRotation...?
        // lerpTargetRotation..?
        if (this._primary && this._primary.length() > 0) {
            Vec3.copy(_tempVec3, this._camera.node.eulerAngles);
            if (this.rotateXEnable) {
                _tempVec3.y -= this._primary.x * deltaTime * this.rotateSpeed;
            }
            if (this.rotateYEnable) {
                _tempVec3.x += this._primary.y * deltaTime * this.rotateSpeed;
            }
            this._camera.node!.setRotationFromEuler(_tempVec3);
            // Quat.fromEuler(_tempQuat, _tempVec3.x, _tempVec3.y, _tempVec3.z);
            // this._camera.node!.setWorldRotation(_tempQuat); // targetRotation
        }
    }

    /**
     * 应用跟随
     */
    public applyFollowNode () {
        if (this.follow) {
            this._targetPosition.add(this.follow.worldPosition);
        }
    }

    /**
     * 播放
     */
    public play () {
        this._isPlay = true;
    }

    /**
     * 暂停
     */
    public stop () {
        this._isPlay = false;
    }

    // 绘制平滑曲线
    private _drawSmoothPath (isDraw: boolean) {
        if (isDraw) {
            if (this.useSmoothPath) {
                this.setMovePositions(this._positions);
                let positions = this._smoothPath!.getBezierPositions();
                this._debugName = DebugDraw.instance.line({ positions, color: Color.RED })
            } else {
                this._debugName = DebugDraw.instance.line({ positions: this._positions, color: Color.RED })
            }
        } else if (this._debugName) {
            DebugDraw.instance.clear(this._debugName);
        }
    }
}

